﻿using System;

namespace IInject
{
	///<summary>
	/// Provides a base class for objects need to dispose of resources.
	///</summary>
	public abstract class DisposableObject : IDisposable
	{
		#region Constructors

		~DisposableObject()
		{
			Dispose(false);
		}

		#endregion

		#region Properties

		/// <summary>
		/// Returns true if the current instance has been disposed of, false otherwise.
		/// </summary>
		public bool IsDisposed { get; private set; }

		/// <summary>
		/// Returns true if the current instance is disposing, false otherwise.
		/// </summary>
		public bool IsDisposing { get; private set; }

		#endregion

		#region Methods

		/// <summary>
		/// Disposes of the res
		/// </summary>
		public virtual void Dispose()
		{
			if (AssertNotDisposedOrDisposing())
			{
				IsDisposing = true;
				
				Dispose(true);
				GC.SuppressFinalize(this);

				IsDisposing = false;
				IsDisposed = true;
			}
		}

		/// <summary>
		/// Verifies that the current instance is not or has not been disposed.
		/// Returns true if it has been disposed or is disposing, throws an exception otherwise.
		/// </summary>
		/// <returns></returns>
		protected bool AssertNotDisposedOrDisposing()
		{
			if (!IsDisposed && !IsDisposing)
			{
				return true;
			}

			throw new ObjectDisposedException(GetType().FullName);
		}
		
		/// <summary>
		/// When overridden in a derived class, disposes of this instances' allocated resources.
		/// </summary>
		protected abstract void Dispose(bool disposing);

		#endregion
	}
}
